package com.swak.frame.api.filter.spring.configuration;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;

import com.swak.frame.SwakConstants;
import com.swak.frame.api.filter.SwakServiceChainFactory;
import com.swak.frame.api.filter.interceptor.ApiFilterAnnotationBeanPostProcessor;
import com.swak.frame.api.filter.interceptor.ApiFilterAnnotationParser;
import com.swak.frame.api.filter.interceptor.ApiFilterOperationSource;
import com.swak.frame.api.filter.interceptor.DefaultApiFilterOperationSource;
import com.swak.frame.api.filter.interceptor.SwakMethodInterceptor;
import com.swak.frame.filter.SwakMethodAnnotationParser;
import com.swak.frame.system.SwakAbstractConfiguration;

@Configuration(proxyBeanMethods = false)
public class ApiFilterConfiguration extends SwakAbstractConfiguration {

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	@ConditionalOnMissingBean(SwakMethodAnnotationParser.class)
	public SwakMethodAnnotationParser swakMethodAnnotationParser() {
		SwakMethodAnnotationParser swakMethodAnnotationParser = new ApiFilterAnnotationParser();
		return swakMethodAnnotationParser;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	@ConditionalOnMissingBean(ApiFilterOperationSource.class)
	public ApiFilterOperationSource apiFilterOperationSource(SwakMethodAnnotationParser swakMethodAnnotationParser) {
		DefaultApiFilterOperationSource operationSource = new DefaultApiFilterOperationSource();
		operationSource.setAnnotationParser(swakMethodAnnotationParser);
		return operationSource;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	@ConditionalOnMissingBean(SwakMethodInterceptor.class)
	public SwakMethodInterceptor swakMethodInterceptor(ApiFilterOperationSource apiFilterOperationSource,SwakServiceChainFactory swakServiceChainFactory) {
		SwakMethodInterceptor interceptor = new SwakMethodInterceptor(swakServiceChainFactory);
		interceptor.setOperationSource(apiFilterOperationSource);
		return interceptor;
	}

	@Bean("internalSwakMethodAdvisor")
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	@ConditionalOnMissingBean(ApiFilterAnnotationBeanPostProcessor.class)
	public ApiFilterAnnotationBeanPostProcessor apiFilterAdvisor(SwakMethodInterceptor swakMethodInterceptor) {
		ApiFilterAnnotationBeanPostProcessor apiFilterAdvisor = new ApiFilterAnnotationBeanPostProcessor(
				swakMethodInterceptor);
		apiFilterAdvisor.setOrder(SwakConstants.ORDER_PRECEDENCE + 2);
		return apiFilterAdvisor;
	}
}
